# main.py
import asyncio
import logging
import os
import subprocess
import sys
from contextlib import asynccontextmanager

from fastapi import FastAPI

from config_manager import config_manager
from exceptions import WorkstationError
from logger_config import setup_logger
import helpr
from models import api_request_model as api_model
from fastapi import Request, status
from fastapi.responses import JSONResponse

from workstation.workstation import WorkstationConfig
from workstation.workstation_manager import WorkstationManager

global VALID_API_KEY  # api key
global OPEN_AUTH  # 开启验证

logger = setup_logger()

workstation_manager = None
_startup_lock = asyncio.Lock()  # 添加全局锁


async def auth_middleware(request: Request, call_next):
    # 白名单路径（不需要验证的接口）
    whitelist = {
        "/docs", "/redoc", "/openapi.json",  # 文档接口
    }

    if OPEN_AUTH == False:
        return await call_next(request)

    # 跳过白名单检查
    if request.url.path in whitelist:
        return await call_next(request)

    # 获取 Authorization 头
    auth_header = request.headers.get("Authorization")

    # 提取并验证 API Key
    api_key = auth_header
    if api_key != VALID_API_KEY:
        return JSONResponse(
            status_code=status.HTTP_401_UNAUTHORIZED,
            content={"status": False, "message": "无效的API KEY"}
        )

    # 验证通过继续处理
    response = await call_next(request)
    return response


@asynccontextmanager
async def startup_event(app: FastAPI):
    """
    Startup event
    :return:
    """
    global workstation_manager
    async with _startup_lock:  # 加锁防止并发
        logger.debug(f"startup_event 调用 (进程 ID: {os.getpid()})")
        if workstation_manager is None:

            # 初始化工作站配置
            workstation_config = WorkstationConfig()
            workstation_config.initial_url = config_manager.get_config("workstation.initial_url",
                                                                       workstation_config.initial_url)
            workstation_config.message_queue_size = config_manager.get_config("workstation.message_queue_size",
                                                                              workstation_config.message_queue_size)
            workstation_config.retry_intervals = config_manager.get_config("workstation.retry_intervals",
                                                                           workstation_config.retry_intervals)
            workstation_config.operation_timeout = config_manager.get_config("workstation.operation_timeout",
                                                                             workstation_config.operation_timeout)
            workstation_config.reuse_context = config_manager.get_config("workstation.reuse_context",
                                                                         workstation_config.reuse_context)

            manager = WorkstationManager(logger=logger, workstation_config=workstation_config)
            await manager.initialize()
            workstation_manager = manager
        else:
            logger.warning("WorkstationManager 已经初始化，跳过重复初始化")
    yield
    await workstation_manager.shutdown()
    logger.info("关闭 workstation manager")


app = FastAPI(lifespan=startup_event)
app.middleware("http")(auth_middleware)


@app.post("/workstations/create")
async def create_workstation(request: api_model.CreateWorkstationRequest):
    try:
        workstation_id = await workstation_manager.create_workstation(
            initial_url=request.initial_url,
            name=request.name,
            workstation_id=request.workstation_id
        )
    except WorkstationError as e:
        return {"status": False, "message": str(e)}
    except Exception as e:
        return {"status": False, "message": str(e)}

    return {"status": True, "workstation_id": workstation_id}


@app.post("/workstations/open")
async def open_workstation(request: api_model.OpenWorkstationRequest):
    try:
        logger.debug(f"打开工作台: {request.workstation_id}")
        await workstation_manager.open_workstation(request.workstation_id)
    except WorkstationError as e:
        return {"status": False, "message": str(e)}
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "message": "工作台打开成功"}


@app.get("/workstations/list")
async def get_workstation_all(keyword: str = None):
    """获取工作台列表"""
    try:
        logger.debug(f"获取工作台列表: {keyword}")
        workstations = await workstation_manager.list_workstations(keyword)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "data": workstations}


@app.post("/workstations/set_callback_url")
async def set_callback_url(request: api_model.SetCallbackUrlRequest):
    try:
        logger.debug(f"设置回调地址: {request.url}")
        workstation_manager.callback_handler.add_callback_endpoint(request.url)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "message": "回调地址设置成功", "url": request.url}


@app.post("/workstations/del_callback_url")
async def set_callback_url(request: api_model.SetCallbackUrlRequest):
    try:
        logger.debug(f"删除回调地址: {request.url}")
        workstation_manager.callback_handler.delete_callback_endpoint(request.url)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "message": "回调地址删除成功", "url": request.url}


@app.post("/{workstation_id}/user_order")
async def get_user_order(workstation_id: str, request: api_model.GetUserOrderRequest):
    try:
        logger.debug(f"获取用户订单: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        orders = await workstation.get_user_orders(request.uid)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "data": orders}


@app.post("/{workstation_id}/send_message")
async def send_message(workstation_id: str, request: api_model.SendMessageRequest):
    try:
        logger.debug(f"发送消息: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        await workstation.send_message(request.uid, request.message)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "message": "消息发送成功"}


@app.get("/{workstation_id}/cs_list")
async def get_assign_cs_list(workstation_id: str):
    try:
        logger.debug(f"获取客服列表: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        cs_list = await workstation.get_assign_cs_list()
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "data": cs_list}


@app.post("/{workstation_id}/move_conversation")
async def move_conversation(workstation_id: str, request: api_model.MoveConversationRequest):
    try:
        logger.debug(f"转移会话: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        await workstation.move_conversation(request.uid, request.username, request.reason)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "message": "会话转移成功"}


@app.post("/{workstation_id}/update_note_tag")
async def update_note_tag(workstation_id: str, request: api_model.UpdateNoteTagRequest):
    try:
        logger.debug(f"更新备注标签: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        await workstation.update_note_tag(request.order_sn, request.remark, request.remark_tag, request.remark_tag_name)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "message": "备注标签更新成功"}


@app.post("/{workstation_id}/recommend_goods")
async def recommend_goods(workstation_id: str, request: api_model.GetRecommendGoodsRequest):
    try:
        logger.debug(f"获取推荐商品: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        goods = await workstation.recommend_goods(request.uid, request.page_num, request.page_size)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "data": goods}


@app.post("/{workstation_id}/send_user_help_link")
async def send_user_help_link(workstation_id: str, request: api_model.SendUserHelpLinkRequest):
    try:
        logger.debug(f"发送用户帮助链接: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        await workstation.send_user_help_link(request.link_type, request.uid, request.order_sn)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "message": "用户帮助链接发送成功"}


@app.post("/{workstation_id}/order_pickup_info")
async def get_order_pickup_info(workstation_id, request: api_model.OrdergeneralRequest):
    try:
        logger.debug(f"获取订单取货信息: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        order_pickup_info = await workstation.get_order_pickup_info(request.order_sn)
    except Exception as e:
        return {"status": False, "message": str(e)}
    return {"status": True, "data": order_pickup_info}


@app.post("/{workstation_id}/send_mall_goods_card")
async def send_mall_goods_card(workstation_id, request: api_model.SendGoodsCardRequest):
    try:
        logger.debug(f"发送商品卡片: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        await workstation.send_mall_goods_card(request.uid, request.goods_id)
        return {"status": True, "message": "商品卡片发送成功"}
    except Exception as e:
        return {"status": False, "message": str(e)}


@app.post("/{workstation_id}/small_transfer_application_apply")
async def small_transfer_application_apply(workstation_id, request: api_model.ApplicationApplyRequest):
    try:
        logger.debug(f"发起小额打款申请: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        success, data, error_msg = await workstation.small_transfer_application_apply(
            request.order_sn,
            request.transfer_reason,
            request.transfer_amount,
            request.apply_note
        )
        if success:
            return {"status": True, "message": "小额打款申请提交成功", "data": data}
        else:
            return {"status": False, "message": error_msg}
    except Exception as e:
        return {"status": False, "message": str(e)}


@app.post("/{workstation_id}/ask_refund_apply")
async def ask_refund_apply(workstation_id, request: api_model.AskRefundApplyRequest):
    try:
        logger.debug(f"申请退款: {workstation_id}")
        workstation = await workstation_manager.get_workstation(workstation_id)
        success, data, error_msg = await workstation.ask_refund_apply(
            order_sn=request.order_sn,
            after_sales_type=request.after_sales_type,
            question_type=request.question_type,
            refund_amount=request.refund_amount,
            message=request.message
        )
        if success:
            return {"status": True, "message": "退款申请提交成功", "data": data}
        else:
            return {"status": False, "message": error_msg}
    except  Exception as e:
        return {"status": False, "message": str(e)}


def handle_run_params():
    params_arr = sys.argv
    for param in params_arr:
        if param.startswith("--debug"):
            logger.setLevel(logging.DEBUG)
        if param.startswith("--api_auth"):
            api_auth = param.split("=")[1]
            # 设置环境变量
            os.environ["PDD_OPEN_API_AUTH"] = api_auth
        if param.startswith("--api_secret"):
            api_secret = param.split("=")[1]
            # 设置环境变量
            os.environ["PDD_OPEN_API_SECRET"] = api_secret
        if param.startswith("--help"):
            _print_help()
            sys.exit(0)


def _print_help():
    print("Usage: python main.py [options]")
    print("Options:")
    print("  --debug                  开启debug模式")
    print("  --api_auth=<value>       设置环境变量: PDD_OPEN_API_AUTH")
    print("  --api_secret=<value>     设置环境变量: PDD_OPEN_API_SECRET")
    print("")
    print("Example:")
    print("  python main.py --debug --api_auth=xxxx --api_secret=xxxx")


def _check_playwright():
    # 检查当前运行目录下的  ms-playwright目录是否为空
    ms_playwright_dir = os.path.join(os.getcwd(), "ms-playwright")
    data_dir = os.path.join(os.getcwd(), "data")

    if not os.path.exists(ms_playwright_dir):
        os.makedirs(ms_playwright_dir)
    if not os.path.exists(data_dir):
        os.makedirs(data_dir)

    if not os.listdir(ms_playwright_dir):
        # 如果为空，则下载
        print("playwright所需要的浏览器未安装，正在准备下载chrome浏览器库")
        # 设置临时环境变量
        os_env = os.environ.copy()
        os_env["PLAYWRIGHT_BROWSERS_PATH"] = ms_playwright_dir
        run_ret = subprocess.run(["playwright", "install", "chromium"], env=os_env)
        if run_ret.returncode != 0:
            print("下载失败，请手动下载chrome浏览器库至该目录下：" + ms_playwright_dir)
            sys.exit(1)
        print("chrome浏览器库下载完成，请重新运行本程序！")
        sys.exit(0)


if __name__ == "__main__":
    handle_run_params()
    VALID_API_KEY = config_manager.get_config("base.valid_api_key", "")
    OPEN_AUTH = config_manager.get_config("base.open_auth", False)

    _check_playwright()

    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8001, workers=1, reload=False)
